package com.lx.onbording.vshe.testassignment.core.transformer;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.milyn.Smooks;
import org.milyn.container.ExecutionContext;
import org.milyn.event.report.HtmlReportGenerator;
import org.milyn.payload.JavaResult;
import org.milyn.payload.JavaSource;
import org.milyn.persistence.util.PersistenceUtil;
import org.milyn.scribe.adapter.hibernate.SessionRegister;
import org.milyn.scribe.adapter.jpa.EntityManagerRegister;
import org.milyn.scribe.register.DaoRegister;
import org.xml.sax.SAXException;

import com.lx.onbording.vshe.testassignment.core.domain.Product;
import com.lx.onbording.vshe.testassignment.core.dto.OrderItemDTO;

public abstract class GenericDTOTransformer<E, D> implements
		DTOTransformer<E, D> {

	private Smooks smooks;
	private Class<E> entityClass;
	private Class<D> dtoClass;

	@PersistenceContext
	protected EntityManager em;

	public GenericDTOTransformer() throws IOException, SAXException {

		ParameterizedType genericSuperclass = (ParameterizedType) getClass()
				.getGenericSuperclass();
		this.entityClass = (Class<E>) genericSuperclass
				.getActualTypeArguments()[0];
		this.dtoClass = (Class<D>) genericSuperclass.getActualTypeArguments()[0];
		init();
	}

	@PostConstruct
	protected void init() throws IOException, SAXException {
		if (smooks == null) {
			smooks = new Smooks("smooks/" + getClass().getSimpleName()
					+ "-config.xml");
		}
	}

	@PreDestroy
	public void close() {
		if (smooks != null)
			smooks.close();
	}

	public D toDTO(E entity) {
		ExecutionContext executionContext = smooks.createExecutionContext();

		DaoRegister register = new EntityManagerRegister(em);
		PersistenceUtil.setDAORegister(executionContext, register);
		try {
			executionContext.setEventListener(new HtmlReportGenerator(
					"target/report/" + getClass().getSimpleName()
							+ "-report.html"));
		} catch (Exception e) {
			e.printStackTrace();
		}
		JavaSource source = new JavaSource(entity);
		JavaResult result = new JavaResult();

		smooks.filterSource(executionContext, source, result);

		return (D) result.getBean(dtoClass.getSimpleName());
	}

	public E fromDTO(D dto) {

		ExecutionContext executionContext = smooks.createExecutionContext();
		DaoRegister register = new EntityManagerRegister(em);
		PersistenceUtil.setDAORegister(executionContext, register);

		try {
			executionContext.setEventListener(new HtmlReportGenerator(
					"target/report/" + getClass().getSimpleName()
							+ "-report.html"));
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		JavaSource source = new JavaSource(dto);
		JavaResult result = new JavaResult();

		smooks.filterSource(executionContext, source, result);

		return (E) result.getBean(entityClass.getSimpleName());
	}

	public List<D> toDTOList(List<E> entityList) {
		List<D> result = new ArrayList<D>();
		for (E e : entityList) {
			result.add(toDTO(e));
		}
		return result;
	}

	public List<E> fromDTOList(List<D> dtoList) {
		List<E> result = new ArrayList<E>();
		for (D dto : dtoList) {
			result.add(fromDTO(dto));
		}
		return result;
	}

}
